package cn.hfjava.kz.common.listener;


import cn.hfjava.kz.common.annotation.ExcelValid;
import cn.hfjava.kz.entity.excel.StudentExcel;
import cn.hfjava.kz.exception.BizException;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Consumer;

/**
 * 读取excel数据
 */
@Slf4j
public class StudentDataListener extends AnalysisEventListener<StudentExcel> {

    /**
     * 每一批处理数据量
     */
    private static final int BATCH_COUNT = 100;

    /**临时存储正常数据集合,最大存储100*/
    private List<StudentExcel> list = Lists.newArrayListWithExpectedSize(BATCH_COUNT);

    /**自定义消费者函数接口用于自定义监听器中数据组装*/
    private final Consumer<List<StudentExcel>> successConsumer;

    public StudentDataListener(Consumer<List<StudentExcel>> successConsumer) {
        this.successConsumer = successConsumer;
    }

    @Override
    public void invoke(StudentExcel studentExcel, AnalysisContext analysisContext) {
        if (studentExcel != null) {
            log.info("解析到一条数据:{}", studentExcel);
        }

        // 校验数据
        valid(studentExcel);

        list.add(studentExcel);
        if(list.size() >= BATCH_COUNT){
            log.info("已解析{}条数据",list.size());
            list.clear();
        }
    }

    public static void valid(Object obj) throws BizException {
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            Object fieldValue = null;
            try {
                fieldValue = field.get(obj);
            } catch (IllegalAccessException e) {
                throw new BizException(400,field.getAnnotation(ExcelValid.class).message());
            }
            // 是否包含必填校验注解
            boolean isExcelValid  = field.isAnnotationPresent(ExcelValid.class);
            if(isExcelValid && Objects.isNull(fieldValue)){
                 throw new BizException(400,field.getAnnotation(ExcelValid.class).message());
            }
        }
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        /*log.info("解析到一条表头数据:{}", JSONUtil.toJsonPrettyStr(headMap));
        List<String> headList = new ArrayList<>();
        Field[] fields = StudentExcel.class.getDeclaredFields();
        for (int i = 0; i < fields.length; i++) {
            ExcelProperty excelProperty = fields[i].getAnnotation(ExcelProperty.class);
            if(excelProperty == null) {
                continue;
            }
            headList.add(excelProperty.value()[0]);
        }
        int count = 0;
        for (Integer key : headMap.keySet()) {
            log.info("表头数据校验:{}", headMap.get(key));
            if (headMap.get(key) == null) {
                throw new BizException(400, "第" + (count + 1) + "列表头为空");
            }
            if (count == headList.size()) {
                throw new BizException(400, "上传文件表头与Excel模板表头个数不相等");
            }
            if(! headMap.get(key).equals(headList.get(count))) {
                 throw new BizException(400, "上传文件表头与Excel模板表头顺序不一致");
            }
            count++;
        }*/
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        if (CollectionUtils.isNotEmpty(list)) {
            successConsumer.accept(list);
        }
    }
}
